//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System.Collections;

namespace CommunityServer.Components
{
	/// <summary>
	/// The base syndication writer for a RSS feed.
	/// </summary>
	public abstract class BaseRssWriter : BaseSyndicationWriter
	{
        private string baseGuid = null;
		/// <summary>
		/// Constructs a writer for an RSS feed.
		/// </summary>
		/// <param name="posts">The entries to write as part of the feed.</param>
		public BaseRssWriter(ArrayList posts, Section s, string baseUrl) : base(posts,s, baseUrl)
		{
            baseGuid = CSContext.Current.SiteSettings.PublicSiteKey.ToString();
		}

		protected virtual string Title
		{
			get
			{
				return CurrentSection.Name;
			}
		}


        
		/// <summary>
		/// Build the feed.
		/// </summary>
		protected override void Build()
		{
            if(!Globals.IsNullorEmpty(this.StyleSheet))
            {
                this.WriteStyleSheet(StyleSheet);
            }

			StartDocument();
			SetNamespaces();
			StartChannel();
			WriteChannel();
			foreach(Post p in this.posts)
			{
				StartItem();
				WriteItem(p);
				EndItem();
			}
			EndChannel();
			EndDocument();
		}

		/// <summary>
		/// Output the rss base element.
		/// </summary>
		protected virtual void StartDocument()
		{
			this.WriteStartElement("rss");
			this.WriteAttributeString("version", "2.0");
		}

		/// <summary>
		/// Output the RSS namespaces used in the feed.
		/// </summary>
        protected virtual void SetNamespaces()
        {
            this.WriteAttributeString("xmlns:dc", "http://purl.org/dc/elements/1.1/");
            this.WriteAttributeString("xmlns:slash", "http://purl.org/rss/1.0/modules/slash/");
			this.WriteAttributeString("xmlns:wfw", "http://wellformedweb.org/CommentAPI/");
        }


		/// <summary>
		/// Output the channel element.
		/// </summary>
		protected void StartChannel()
		{
			this.WriteStartElement("channel");
		}

		/// <summary>
		/// Output the header contents of the channel element.
		/// </summary>
		protected abstract void WriteChannel();
//		{
//			//BuildChannel(config.FullyQualifiedUrl, config.SubTitle, config.Language);
//		}

        protected void BuildChannel(string link, string description)
        {
            BuildChannel(link,description,"en-US");
        }

		/// <summary>
		/// Actually build the contents of the channel element.
		/// </summary>
		/// <param name="link">The link element of the channel.</param>
		/// <param name="description">The description element of the channel.</param>
		/// <param name="lang">The language element of the channel.</param>
		protected void BuildChannel(string link, string description, string lang)
		{
			this.WriteElementString("title", Title);			
			this.WriteElementString("link", FormatUrl(link));
			this.WriteElementString("description", description);
			this.WriteElementString("dc:language", lang);
			this.WriteElementString("generator", SiteStatistics.CommunityServerVersionVersionInfo);
		}

		/// <summary>
		/// Output an item element.
		/// </summary>
		protected void StartItem()
		{
			this.WriteStartElement("item");
		}

        protected abstract string BuildLink(Post p);

        protected virtual void PostComments(Post p)
        {
//            // optional for CommentApi Post location
//            this.WriteElementString("wfw:comment", uformat.CommentApiUrl(entry.EntryID));
//            // optional url for comments
//            this.WriteElementString("comments", entry.Link + "#Feedback");
//            // optional comment count
            this.WriteElementString("slash:comments", p.Replies.ToString());
//            // optional commentRss feed location
//            this.WriteElementString("wfw:commentRss", uformat.CommentRssUrl(entry.EntryID));
//            // optional trackback location
//            this.WriteElementString("trackback:ping", uformat.TrackBackUrl(entry.EntryID));
        }

        protected virtual void WritePostEnclosure(Post p)
        {
            PostAttachmentMetaData pa = p.Attachment;
            if(pa != null)
            {
                this.WriteStartElement("enclosure");
                this.WriteAttributeString("url",EnclosureUrl(pa));
                this.WriteAttributeString("length",pa.Length.ToString());
                this.WriteAttributeString("type",pa.ContentType);
                this.WriteEndElement();
            }
        }

        protected virtual void WriteVideoEnclosure(Post p)
        {
            
            if(p.HasVideo)
            {
                this.WriteStartElement("enclosure");
                this.WriteAttributeString("url",p.VideoUrl);
                this.WriteAttributeString("length","0");
                this.WriteAttributeString("type",p.VideoContentType);
                this.WriteEndElement();
            }
        }

        

        protected virtual void PostBody(Post p)
        {
            this.WriteElementString("description",p.RenderedBody(PostTarget.Syndication));
            
        }

        protected virtual string WritePubDate(Post p)
        {
            return p.PostDate.ToUniversalTime().ToString("r");
        }

		protected virtual string GetUserName(Post p)
		{
			return p.Username;
		}

		/// <summary>
		/// Actually write the contents of an item element.
		/// </summary>
		protected virtual void WriteItem(Post p)
		{
			// Subject is already HtmlEncoded in DB
			this.WriteElementString("title", Globals.HtmlDecode(p.Subject));
			// core
			this.WriteElementString("link", FormatUrl(BuildLink(p)));
			
			// core
			this.WriteElementString("pubDate",WritePubDate(p));
            
            this.WriteStartElement("guid");
            this.WriteAttributeString("isPermaLink","false");
            this.WriteString(string.Format("{0}:{1}",baseGuid,p.PostID));
            this.WriteEndElement();

            this.WriteElementString("dc:creator",GetUserName(p));

			//this.WriteElementString("guid", BuildLink(p));

            PostComments(p);
            PostBody(p);

            //RSS is a little vague on multiple attachments, but we will error on the 
            //side of too much info. If there is both a video and attachment
            //in at least CS 2.0, we will include two enclosures

            if(p.HasAttachment)
                WritePostEnclosure(p);

            if(p.HasVideo)
                WriteVideoEnclosure(p);
                




//			// core
//			this.WriteElementString(
//				"description", // Tag
//				string.Format(
//					"{0}{1}", // tag def
//					entry.SyndicateDescriptionOnly ? entry.Description : entry.Body,  //use desc or full post
//					(UseAggBugs && settings.Tracking.EnableAggBugs) ? TrackingUrls.AggBugImage(uformat.AggBugkUrl(entry.EntryID)) : null //use aggbugs
//				)
//			);

		}

		/// <summary>
		/// Write the end tag for an item element.
		/// </summary>
		protected void EndItem()
		{
			this.WriteEndElement();
		}

		/// <summary>
		/// Write the end tag for a channel element.
		/// </summary>
		protected void EndChannel()
		{
			this.WriteEndElement();
		}

		/// <summary>
		/// Write the end tag for a rss element.
		/// </summary>
		protected void EndDocument()
		{
			this.WriteEndElement();
		}
	}
}
